package com.thd.springboot.framework.utils;

import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * com.thd.springboot.framework.utils.DateUtils
 *
 * @author: wanglei62
 * @DATE: 2020/4/8 19:15
 **/
public class DateUtils {

    private static final String dateFormat = "yyyy-MM-dd HH:mm:ss";
    private static final String shortDateFormat = "yyyy-MM-dd";
    private static final String timestampFormat = "^\\d+$";


    /**
     * 1.LocalDate转Date
     *
     * LocalDate nowLocalDate = LocalDate.now();
     * Date date = Date.from(localDate.atStartOfDay(ZoneOffset.ofHours(8)).toInstant());
     *
     * 2.LocalDateTime转Date
     *
     * LocalDateTime localDateTime = LocalDateTime.now();
     * Date date = Date.from(localDateTime.atZone(ZoneOffset.ofHours(8)).toInstant());
     *
     * 3.Date转LocalDateTime(LocalDate)
     *
     * Date date =newDate();
     * LocalDateTime localDateTime = date.toInstant().atZone(ZoneOffset.ofHours(8)).toLocalDateTime();
     * LocalDate localDate = date.toInstant().atZone(ZoneOffset.ofHours(8)).toLocalDate();
     *
     * 4.LocalDate转时间戳
     *
     * LocalDate localDate = LocalDate.now();
     * longtimestamp = localDate.atStartOfDay(ZoneOffset.ofHours(8)).toInstant().toEpochMilli();
     *
     * 5.LocalDateTime转时间戳
     *
     * LocalDateTime localDateTime = LocalDateTime.now();
     * longtimestamp = localDateTime.toInstant(ZoneOffset.ofHours(8)).toEpochMilli();
     *
     * 6.时间戳转LocalDateTime(LocalDate)
     *
     * longtimestamp = System.currentTimeMillis();
     * LocalDate localDate = Instant.ofEpochMilli(timestamp).atZone(ZoneOffset.ofHours(8)).toLocalDate();
     * LocalDateTime localDateTime = Instant.ofEpochMilli(timestamp).atZone(ZoneOffset.ofHours(8)).toLocalDateTime();
     */
    /**
     * 字符串 转 Date
     * @param value
     * @return
     */
    public static Date stringToDate(String value){
        if(value == null || value.trim().equals("") || value.equalsIgnoreCase("null")){
            return null;
        }
        try{
            if(value.contains("-")){
                SimpleDateFormat sdf;
                if(value.contains(":")){ // 长日期 yyyy_MM_dd HH:mm:ss
                    sdf = new SimpleDateFormat(dateFormat);
                }else{   // 短日期 yyyy_MM_dd
                    sdf = new SimpleDateFormat(shortDateFormat);
                }
                return sdf.parse(value);
            }else if(value.matches(timestampFormat)){ // 时间戳 1585875084
                Long timestamp = new Long(value);
                return new Date(timestamp);
            }
        }catch(Exception e){
            throw new RuntimeException(String.format(" parser %s to Date Failed",value));
        }
        throw new RuntimeException(String.format(" parser %s to Date Failed",value));
    }

    /**
     * 字符串 转 Timestamp
     * @param value
     * @return
     */
    public static Timestamp stringToTimestamp(String value){
        Date d = DateUtils.stringToDate(value);
        return new Timestamp(d.getTime());
    }


    /**
     * 字符串 转 LocalDate
     * @param value
     * @return
     */
    public static LocalDate stringToLocalDate(String value){
        Date d = DateUtils.stringToDate(value);
        return DateUtils.dateToLocalDate(d);
    }

    /**
     * 字符串 转 LocalDateTime
     * @param value
     * @return
     */
    public static LocalDateTime stringToLocalDateTime(String value){
        Date d = DateUtils.stringToDate(value);
        return DateUtils.dateToLocalDateTime(d);
    }


    /**
     * Date 转 字符串
     * @param d
     * @param pattern 格式
     * @return
     */
    public static String dateToString(Date d , String pattern){
        if(d == null){
            return null;
        }
        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        return sdf.format(d);
    }

    /**
     * Timestamp 转 字符串
     * @param t
     * @param pattern
     * @return
     */
    public static String timestampToString(Timestamp t,String pattern){
        Date d = new Date(t.getTime());
        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        return sdf.format(d);
    }

    /**
     * Timestamp 转 Date
     * @param t
     * @return
     */
    public static Date timestampToDate(Timestamp t){
        if(t == null){
            return null;
        }
        return new Date(t.getTime());
    }

    /**
     * Date 转 Timestamp
     * @param d
     * @return
     */
    public static Timestamp dateToTimestamp(Date d){
        if(d == null){
            return null;
        }
        return new Timestamp(d.getTime());
    }

    /**
     * Date 转 Timestamp
     * @param d
     * @return
     */
    public static LocalDate dateToLocalDate(Date d){
        if(d == null){
            return null;
        }
        return d.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
    }

    /**
     * Date 转 Timestamp
     * @param d
     * @return
     */
    public static LocalDateTime dateToLocalDateTime(Date d){
        if(d == null){
            return null;
        }
        return d.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
    }

    /**
     * Date 转 Timestamp
     * @param d
     * @return
     */
    public static LocalTime dateToLocalTime(Date d){
        if(d == null){
            return null;
        }
        return d.toInstant().atZone(ZoneId.systemDefault()).toLocalTime();
    }

    /**
     * Date 转 Long
     * @param d
     * @return
     */
    public static Long dateToLong(Date d){
        if(d == null){
            return null;
        }
        return d.getTime();
    }

    /**
     * Timestamp 转 Long
     * @param t
     * @return
     */
    public static Long timestampToLong(Timestamp t){
        if(t == null){
            return null;
        }
        return t.getTime();
    }

    /**
     * Date 转 时间戳字符串
     * @param d
     * @return
     */
    public static String dateToLongString(Date d){
        if(d == null){
            return null;
        }
        return String.valueOf(d.getTime());
    }

    /**
     * Timestamp 转 时间戳字符串
     * @param t
     * @return
     */
    public static String timestampToLongString(Timestamp t){
        if(t == null){
            return null;
        }
        return String.valueOf(t.getTime());
    }


    /**
     * 计算两个日期之间的年月列表
     * @param y1
     * @param y2
     * @return
     * @throws Exception
     */
    public List getMonthBetween(String y1, String y2) throws Exception {
//        y1 = "2016-02";// 开始时间
//        y2 = "2019-12";// 结束时间

        try {
            Date startDate = new SimpleDateFormat("yyyy-MM").parse(y1);
            Date endDate = new SimpleDateFormat("yyyy-MM").parse(y2);

            Calendar calendar = Calendar.getInstance();
            calendar.setTime(startDate);
            // 获取开始年份和开始月份
            int startYear = calendar.get(Calendar.YEAR);
            int startMonth = calendar.get(Calendar.MONTH);
            // 获取结束年份和结束月份
            calendar.setTime(endDate);
            int endYear = calendar.get(Calendar.YEAR);
            int endMonth = calendar.get(Calendar.MONTH);
            //
            List<String> list = new ArrayList<String>();
            for (int i = startYear; i <= endYear; i++) {
                String date = "";
                if (startYear == endYear) {
                    for (int j = startMonth; j <= endMonth; j++) {
                        if (j < 9) {
                            date = i + "-0" + (j + 1);
                        } else {
                            date = i + "-" + (j + 1);
                        }
                        list.add(date);
                    }

                } else {
                    if (i == startYear) {
                        for (int j = startMonth; j < 12; j++) {
                            if (j < 9) {
                                date = i + "-0" + (j + 1);
                            } else {
                                date = i + "-" + (j + 1);
                            }
                            list.add(date);
                        }
                    } else if (i == endYear) {
                        for (int j = 0; j <= endMonth; j++) {
                            if (j < 9) {
                                date = i + "-0" + (j + 1);
                            } else {
                                date = i + "-" + (j + 1);
                            }
                            list.add(date);
                        }
                    } else {
                        for (int j = 0; j < 12; j++) {
                            if (j < 9) {
                                date = i + "-0" + (j + 1);
                            } else {
                                date = i + "-" + (j + 1);
                            }
                            list.add(date);
                        }
                    }

                }

            }

            // 所有的月份已经准备好
            //System.out.println(list);
            for(int i = 0;i < list.size();i++){
                System.out.println(list.get(i));
            }
            return list;
        } catch (Exception e) {
//            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }

    }


    /**
     * 获取日期所在周的第一天日期
     * @param d
     * @return
     */
    public static Date findFirstDayOfWeek(Date d){
        Calendar c = Calendar.getInstance();
//        c.setFirstDayOfWeek(Calendar.MONDAY);
        c.setTime(d);
        if(c.get(Calendar.DAY_OF_WEEK) == 1){
            c.add(Calendar.DATE,-7);
        }
        c.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
        return c.getTime();
    }

    /**
     * 获取日期所在周的最后一天日期
     * @param d
     * @return
     */
    public static Date findLastDayOfWeek(Date d){
        Calendar c = Calendar.getInstance();
//        c.setFirstDayOfWeek(Calendar.MONDAY);
        c.setTime(d);
        if(c.get(Calendar.DAY_OF_WEEK) != 1){
            c.add(Calendar.DATE,7);
        }
        c.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
        return c.getTime();
    }

    /**
     * 求两个日期间隔天数
     * @param d1
     * @param d2
     * @return
     */
    public static long getBetweenDays(Date d1,Date d2){
        // 获取相差的天数
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(d1);
        long timeInMillis1 = calendar.getTimeInMillis();
        calendar.setTime(d2);
        long timeInMillis2 = calendar.getTimeInMillis();

        long betweenDays =  (timeInMillis2 - timeInMillis1) / (1000L*3600L*24L);
        return betweenDays;
    }

    /**
     * 根据某个日期，查询该日期所在范围的第一天
     * @param d 日期
     * @param calendarType 范围类型,参见Calendar类
     *
     * @return
     */
    public static Date testDay(Date d,Integer calendarType) throws Exception{
        Calendar c = Calendar.getInstance();
        // 设置每周的第一天是周一

        String day = new SimpleDateFormat("yyyy-MM-dd").format(d);
//        d = new SimpleDateFormat("yyyy-MM-dd").parse(day);
        c.setTime(d);
        c.setFirstDayOfWeek(Calendar.MONDAY);

        System.out.println("==== 日期："+ day);
        System.out.println("年份:"+c.get(Calendar.YEAR));
        System.out.println("月份:"+(c.get(Calendar.MONTH)+1));
        System.out.println("年周次:"+c.get(Calendar.WEEK_OF_YEAR));
        System.out.println("月周次:"+c.get(Calendar.WEEK_OF_MONTH));
        System.out.println("年中的第几天:"+c.get(Calendar.DAY_OF_YEAR));
        System.out.println("月的第几天:"+c.get(Calendar.DAY_OF_MONTH));
        System.out.println("星期中的第几天:"+(c.get(Calendar.DAY_OF_WEEK)));

        Integer minYear = c.getActualMinimum(Calendar.DAY_OF_YEAR);
        Integer maxYear = c.getActualMaximum(Calendar.DAY_OF_YEAR);
        System.out.println("当前年的最大最小日期："+ minYear+"-"+maxYear);


        Integer minMonth = c.getActualMinimum(Calendar.DAY_OF_MONTH);
        Integer maxMonth = c.getActualMaximum(Calendar.DAY_OF_MONTH);
        System.out.println("当前月的最大最小日期："+ minMonth+"-"+maxMonth);

        c.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
        System.out.println("当前周的最大最小日期："+ new SimpleDateFormat("yyyy-MM-dd").format(c.getTime()));
        c.add(Calendar.DATE,7);
        c.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
//        c.add(Calendar.DATE,7);
        System.out.println("当前周的最大最大日期："+ new SimpleDateFormat("yyyy-MM-dd").format(c.getTime()));

        return d;
    };

//    public static void main(String[] args) throws Exception{
//
//
//        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
//        String day = "2022-01-01";
//        Date d1 = sdf.parse(day);
//        Date d2 = sdf.parse(day);
//        Date d3 = sdf.parse(day);
//
//        DateUtils.testDay(d1,Calendar.YEAR);
//
//        System.out.println(sdf.format(DateUtils.findFirstDayOfWeek(d2)));
//        System.out.println(sdf.format(DateUtils.findLastDayOfWeek(d3)));
//
//
//        long i = DateUtils.getBetweenDays(sdf.parse("2022-02-13"), sdf.parse("2023-02-13"));
//        System.out.println(i);
//
//
//
//
//    }
}
